﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Reflection;

using CreateDefect.Models;

namespace CreateDefect.Domain
{
    public class QCDefect : IDefect
    {
        #region Constructor
        /// <summary>
        /// No default constructor
        /// </summary>
        private QCDefect() { }

        /// <summary>
        /// For creating new defects only
        /// </summary>
        /// <param name="TDConnection">Connection to Quality Center</param>
        internal QCDefect(TDAPIOLELib.TDConnection TDConnection)
        {
            try
            {
                TDAPIOLELib.BugFactory fact = (TDAPIOLELib.BugFactory)TDConnection.BugFactory;

                this.bug = (TDAPIOLELib.Bug)fact.AddItem(System.DBNull.Value);
            }
            catch (Exception ex) { throw ex; }
        }

        /// <summary>
        /// For using an existing defect
        /// </summary>
        /// <param name="TDConnection">Connection to Quality Center</param>
        /// <param name="BugId">The ID of the defect</param>
        internal QCDefect(TDAPIOLELib.TDConnection TDConnection, int BugId)
        {
            try
            {
                TDAPIOLELib.BugFactory fact = (TDAPIOLELib.BugFactory)TDConnection.BugFactory;
                this.bug = (TDAPIOLELib.Bug)fact[BugId];

                FillFields();
            }
            catch (Exception ex) { throw ex; }
        }
        #endregion

        #region Private Methods

        private void FillFields()
        {
            Summary = this.bug.Summary;
            Description = this.bug["BG_DESCRIPTION"].ToString();
            Priority = this.bug.Priority;
            Severity = this.bug["BG_SEVERITY"].ToString();
            Status = this.bug.Status;
            Id = this.bug.ID;
        }

        /// <summary>
        /// There's has to be a better why, just don't have time
        /// </summary>
        private void AssignFields()
        {
            this.bug.Summary = Summary;
            this.bug["BG_DESCRIPTION"] = Description;
            this.bug.Priority = Priority;
            this.bug["BG_SEVERITY"] = Severity;
            this.bug.Status = Status;
        }

        #endregion

        #region Private Properties
        private TDAPIOLELib.Bug bug { get; set; }
        #endregion

        #region Public Methods

        public void Post()
        {
            try 
            {
                AssignFields();
                this.bug.Post();
                Id = this.bug.ID;
            }
            catch (Exception ex) { throw ex; }
        }

        #endregion

        #region Public Properties
        /// <summary>
        /// The Title of the defect
        /// </summary>
        public string Summary
        {
            get;
            set;
        }

        /// <summary>
        /// The descritpion of the defect in HTML
        /// </summary>
        public string Description
        {
            get;
            set;
        }

        /// <summary>
        /// The date the defect was detected
        /// </summary>
        public DateTime? DetectedDate
        {
            get;
            set;
        }

        /// <summary>
        /// The priority of the defect
        /// </summary>
        public string Priority
        {
            get;
            set;
        }

        /// <summary>
        /// The severity of the defect
        /// </summary>
        public string Severity
        {
            get;
            set;
        }

        /// <summary>
        /// The status of the defect
        /// </summary>
        public string Status
        {
            get;
            set;
        }

        public int Id
        {
            get;
            private set;
        }
        #endregion

        /// <summary>
        /// Cast a UserDefect object to a QCDefect
        /// </summary>
        /// <param name="UserDefect">The user defect</param>
        /// <returns>New instance of QCDefect</returns>
        public static explicit operator QCDefect(UserDefect UserDefect)
        {
            try
            {
                QCConnection connection = (QCConnection)HttpContext.Current.Session["QCConnection"];

                Type sourceType = UserDefect.GetType();
                Type destinationType = typeof(QCDefect);

                QCDefect defect = new QCDefect(connection.TDConnection);

                // only get the base type properties
                foreach (PropertyInfo sourceProperty in sourceType.GetInterface("IDefect").GetProperties())
                {
                    PropertyInfo destinationProperty = destinationType.GetProperty(sourceProperty.Name);
                    if (destinationProperty != null)
                        destinationProperty.SetValue(defect, sourceProperty.GetValue(UserDefect, null), null);
                }

                return defect;
            }
            catch { return null; }
        }
    }
}